package de.streblow.justscan;

import java.io.IOException;

import de.streblow.justscan.AboutDialog;
import de.streblow.justscan.HelpDialog;
import de.streblow.justscan.OptionsActivity;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.view.Menu;
import android.view.MenuItem;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.RingtoneManager;
import android.media.ToneGenerator;
import android.net.Uri;
import android.view.Surface;
import android.widget.FrameLayout;

//Import ZBar Class files
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import net.sourceforge.zbar.Config;

public class JustScanActivity extends Activity {

	private Camera mCamera;
	private CameraPreview mPreview;
	private Handler autoFocusHandler;
	private Activity mActivity;
	private int mScanAreaColor;
	private int mScanAreaWidth;
	private int mScanAreaHeight;
	private int mScanAreaEdgelet;
	private boolean mPortraitDefault;
	private ImageScanner scanner;
	private String barcodeString = "";
	private boolean previewing = false;

	static {
		System.loadLibrary("iconv");
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_justscan);
		SharedPreferences shared = getSharedPreferences("preferences", MODE_PRIVATE);
		int scanareacolor = shared.getInt("scanareacolor", 2);
		switch (scanareacolor) {
		case 0:
			mScanAreaColor = Color.RED;
			break;
		case 1:
			mScanAreaColor = Color.WHITE;
			break;
		case 2:
			mScanAreaColor = Color.YELLOW;
			break;
		case 3:
			mScanAreaColor = Color.GREEN;
			break;
		default:
			mScanAreaColor = Color.RED;
		}
		mScanAreaWidth = shared.getInt("scanareawidth", 95);
		mScanAreaHeight = shared.getInt("scanareaheight", 15);
		mScanAreaEdgelet = shared.getInt("scanareaedgelet", 10);
		mPortraitDefault = shared.getBoolean("portraitdefault", false);
		autoFocusHandler = new Handler();
		mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
		scanner = new ImageScanner();
		scanner.setConfig(0, Config.X_DENSITY, 3);
		scanner.setConfig(0, Config.Y_DENSITY, 3);
		mPreview = new CameraPreview(this, mCamera, previewCallback, autoFocusCallback,
				mScanAreaColor, mScanAreaWidth, mScanAreaHeight, mScanAreaEdgelet);
	
		FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
		preview.addView(mPreview);
		mCamera.setPreviewCallback(previewCallback);
		mCamera.startPreview();
		previewing = false;
		mCamera.autoFocus(autoFocusCallback);
		mActivity = (Activity)this;
		TextView tvScanning = (TextView) findViewById(R.id.textviewScanning);
		tvScanning.setTextColor(mScanAreaColor);
		tvScanning.setText("");
		final ImageButton button1 = (ImageButton) findViewById(R.id.imageButton1);
		button1.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if (previewing) {
					previewing = false;
					TextView tvScancode = (TextView) findViewById(R.id.textviewScancode);
					tvScancode.setText("");
					TextView tvScanning = (TextView) findViewById(R.id.textviewScanning);
					tvScanning.setText("");
				} else {
					previewing = true;
					TextView tvScancode = (TextView) findViewById(R.id.textviewScancode);
					tvScancode.setText("");
					TextView tvScanning = (TextView) findViewById(R.id.textviewScanning);
					tvScanning.setTextColor(mScanAreaColor);
					tvScanning.setText(getResources().getString(R.string.scanning));
				}
			}
		});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch (item.getItemId())
		{
		case R.id.action_settings:
			previewing = false;
			Intent intent = new Intent(JustScanActivity.this, OptionsActivity.class);
			startActivityForResult(intent, 0);
			return true;
		case R.id.action_help:
			HelpDialog help = new HelpDialog(this);
			help.setTitle(R.string.help_title);
			help.show();
			return true;
		case R.id.action_about:
			AboutDialog about = new AboutDialog(this);
			about.setTitle(R.string.about_title);
			about.show();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	public void onPause() {
		super.onPause();
		releaseCamera();
	}

	public void onResume() {
		super.onResume();
		previewing = false;
		if (mCamera == null) {
			mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
			scanner = new ImageScanner();
			scanner.setConfig(0, Config.X_DENSITY, 3);
			scanner.setConfig(0, Config.Y_DENSITY, 3);
			mPreview = new CameraPreview(this, mCamera, previewCallback, autoFocusCallback,
					mScanAreaColor, mScanAreaWidth, mScanAreaHeight, mScanAreaEdgelet);
		
			FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
			preview.addView(mPreview);
			mCamera.setPreviewCallback(previewCallback);
			mCamera.startPreview();
			mCamera.autoFocus(autoFocusCallback);
		}
	}

	// A safe way to get an instance of the Camera object
	public static Camera getCameraInstance(){
		Camera c = null;
		try {
			c = Camera.open();
		} catch (Exception e){
		}
		return c;
	}

	private void releaseCamera() {
		if (mCamera != null) {
			previewing = false;
			mCamera.setPreviewCallback(null);
			mCamera.release();
			mCamera = null;
		}
	}

	private Runnable doAutoFocus = new Runnable() {
		public void run() {
			if (previewing) {
				if (mCamera != null)
					mCamera.autoFocus(autoFocusCallback);
			} else {
				autoFocusHandler.postDelayed(doAutoFocus, 1000);
			}
		}
	};

	PreviewCallback previewCallback = new PreviewCallback() {
		public void onPreviewFrame(byte[] data, Camera camera) {
			if (!previewing)
				return;
			Parameters parameters = camera.getParameters();
			Size size = parameters.getPreviewSize();
			Image barcode = new Image(size.width, size.height, "Y800");
			barcode.setData(data);
			int areaWidth = size.width;
			int areaHeight = size.height;
			int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
			int degrees = 0;
			switch (rotation) {
				case Surface.ROTATION_0: degrees = 0; break;
				case Surface.ROTATION_90: degrees = 90; break;
				case Surface.ROTATION_180: degrees = 180; break;
				case Surface.ROTATION_270: degrees = 270; break;
			}
			if (mPortraitDefault) {
				degrees = (degrees + 90) % 360;
			}
			if (degrees == 0 || degrees == 180) {
				//device in default layout
				areaWidth = mScanAreaWidth * size.width / 100;
				areaHeight = mScanAreaHeight * size.height / 100;
			} else if (degrees == 90 || degrees == 270) {
				areaWidth = mScanAreaHeight * size.width / 100;
				areaHeight = mScanAreaWidth * size.height / 100;
			}
			barcode.setCrop((size.width - areaWidth) / 2, (size.height - areaHeight) / 2, areaWidth, areaHeight);
			int result = scanner.scanImage(barcode);
			
			if (result != 0) {
				previewing = false;
				playBeep();
				SymbolSet syms = scanner.getResults();
				barcodeString = "";
				for (Symbol sym : syms) {
					barcodeString = barcodeString + sym.getData();
					if (sym.getType() == Symbol.CODABAR) {
						barcodeString = barcodeString + "\n\nFormat: CODABAR";
					} else if (sym.getType() == Symbol.CODE128) {
						barcodeString = barcodeString + "\n\nFormat: CODE128";
					} else if (sym.getType() == Symbol.CODE39) {
						barcodeString = barcodeString + "\n\nFormat: CODE39";
					} else if (sym.getType() == Symbol.CODE93) {
						barcodeString = barcodeString + "\n\nFormat: CODE93";
					} else if (sym.getType() == Symbol.DATABAR) {
						barcodeString = barcodeString + "\n\nFormat: DATABAR";
					} else if (sym.getType() == Symbol.DATABAR_EXP) {
						barcodeString = barcodeString + "\n\nFormat: DATABAR_EXP";
					} else if (sym.getType() == Symbol.EAN13) {
						barcodeString = barcodeString + "\n\nFormat: EAN13";
					} else if (sym.getType() == Symbol.EAN8) {
						barcodeString = barcodeString + "\n\nFormat: EAN8";
					} else if (sym.getType() == Symbol.I25) {
						barcodeString = barcodeString + "\n\nFormat: I25";
					} else if (sym.getType() == Symbol.ISBN10) {
						barcodeString = barcodeString + "\n\nFormat: ISBN10";
					} else if (sym.getType() == Symbol.ISBN13) {
						barcodeString = barcodeString + "\n\nFormat: ISBN13";
					} else if (sym.getType() == Symbol.NONE) {
						barcodeString = barcodeString + "\n\nFormat: NONE";
					} else if (sym.getType() == Symbol.PARTIAL) {
						barcodeString = barcodeString + "\n\nFormat: PARTIAL";
					} else if (sym.getType() == Symbol.QRCODE) {
						barcodeString = barcodeString + "\n\nFormat: QRCODE";
					} else if (sym.getType() == Symbol.UPCA) {
						barcodeString = barcodeString + "\n\nFormat: UPCA";
					} else if (sym.getType() == Symbol.UPCE) {
						barcodeString = barcodeString + "\n\nFormat: UPCE";
					} else {
						barcodeString = barcodeString + "\n\nFormat: ???";
					}
				}
				//scan successfull
				TextView tvScancode = (TextView) findViewById(R.id.textviewScancode);
				tvScancode.setText(barcodeString);
				TextView tvScanning = (TextView) findViewById(R.id.textviewScanning);
				tvScanning.setText("");
			}
		}
	};

	// Mimic continuous auto-focusing
	AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
		public void onAutoFocus(boolean success, Camera camera) {
			autoFocusHandler.postDelayed(doAutoFocus, 1000);
		}
	};

	public void playNotification() {
		Uri defaultRingtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
		MediaPlayer mediaPlayer = new MediaPlayer();
		try {
			mediaPlayer.setDataSource(this, defaultRingtoneUri);
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
			mediaPlayer.prepare();
			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
				@Override
				public void onCompletion(MediaPlayer mp)
				{
					mp.release();
				}
			});
			mediaPlayer.start();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void playBeep() {
		final ToneGenerator tg = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
		tg.startTone(ToneGenerator.TONE_PROP_BEEP);
	}

	public void onActivityResult(int requestCode, int resultCode, Intent intent) {
		if (requestCode == 0) {
			if (resultCode == RESULT_OK) {
				// options may have been changed
				SharedPreferences shared = getSharedPreferences("preferences", MODE_PRIVATE);
				int scanareacolor = shared.getInt("scanareacolor", 2);
				switch (scanareacolor) {
				case 0:
					mScanAreaColor = Color.RED;
					break;
				case 1:
					mScanAreaColor = Color.WHITE;
					break;
				case 2:
					mScanAreaColor = Color.YELLOW;
					break;
				case 3:
					mScanAreaColor = Color.GREEN;
					break;
				default:
					mScanAreaColor = Color.RED;
				}
				mScanAreaWidth = shared.getInt("scanareawidth", 95);
				mScanAreaHeight = shared.getInt("scanareaheight", 15);
				mScanAreaEdgelet = shared.getInt("scanareaedgelet", 10);
				mPortraitDefault = shared.getBoolean("portraitdefault", false);
				mPreview.mScanAreaColor = mScanAreaColor;
				mPreview.mScanAreaWidth = mScanAreaWidth;
				mPreview.mScanAreaHeight = mScanAreaHeight;
				mPreview.mScanAreaEdgelet = mScanAreaEdgelet;
			} else if (resultCode == RESULT_CANCELED) {
				// options have left unchanged
			}
			// restart justscan
			previewing = false;
		}
	}

}
